﻿using eLuk.Common;
using eLuk.Data;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Windows.Input;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Media.Imaging;
using System.Threading.Tasks;
using eLuk.Entity;
using Windows.Storage.Streams;
// The Split Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234234

namespace eLuk
{
	/// <summary>
	/// A page that displays a group title, a list of items within the group, and details for
	/// the currently selected item.
	/// </summary>
	public sealed partial class eLukEmailView : Page
	{

		private NavigationHelper navigationHelper;
		private ObservableDictionary defaultViewModel = new ObservableDictionary();
		//public eLuk.Runtime.IMAPSession Session { get; set; } //new Runtime.IMAPSession( new Runtime.IMAPInitialState(), _server );
		//session.CurrentState
		eLukFolderView folderViewFlyout = null;
		/// <summary>
		/// NavigationHelper is used on each page to aid in navigation and 
		/// process lifetime management
		/// </summary>
		public NavigationHelper NavigationHelper
		{
			get { return this.navigationHelper; }
		}

		/// <summary>
		/// This can be changed to a strongly typed view model.
		/// </summary>
		public ObservableDictionary DefaultViewModel
		{
			get { return this.defaultViewModel; }
		}

		public eLukEmailView()
		{
			this.InitializeComponent();

			// Setup the navigation helper
			this.navigationHelper = new NavigationHelper( this );
			this.navigationHelper.LoadState += navigationHelper_LoadState;
			this.navigationHelper.SaveState += navigationHelper_SaveState;

			// Setup the logical page navigation components that allow
			// the page to only show one pane at a time.
			//this.navigationHelper.GoBackCommand = new RelayCommand( () => this.GoBack(), () => this.CanGoBack() );
			//this.folderListView.SelectionChanged += folderListView_SelectionChanged;

			// Start listening for Window size changes 
			// to change from showing two panes to showing a single pane
			Window.Current.SizeChanged += Window_SizeChanged;
			this.InvalidateVisualState();
		}

		/// <summary>
		/// Populates the page with content passed during navigation.  Any saved state is also
		/// provided when recreating a page from a prior session.
		/// </summary>
		/// <param name="sender">
		/// The source of the event; typically <see cref="NavigationHelper"/>
		/// </param>
		/// <param name="e">Event data that provides both the navigation parameter passed to
		/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
		/// a dictionary of state preserved by this page during an earlier
		/// session.  The state will be null the first time a page is visited.</param>
		private async void navigationHelper_LoadState( object sender, LoadStateEventArgs e )
		{

			App.eLukComponentUpdated += App_eLukComponentUpdated;

			if ( !loginPopup.IsOpen )
			{
				loginPopup.IsOpen = true;
				popUpContent.Width = Window.Current.Bounds.Width;
				txtLoginEmailID.Focus( Windows.UI.Xaml.FocusState.Programmatic );
			}

		}

		private void folderViewFlyout_FolderSelectionChanged( object sender, FolderSelectionChangedEventArgs e )
		{
			this.SelectFolder( e.Folder );
		}

		/// <summary>
		/// Preserves state associated with this page in case the application is suspended or the
		/// page is discarded from the navigation cache.  Values must conform to the serialization
		/// requirements of <see cref="SuspensionManager.SessionState"/>.
		/// </summary>
		/// <param name="navigationParameter">The parameter value passed to
		/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
		/// </param>
		/// <param name="sender">The source of the event; typically <see cref="NavigationHelper"/></param>
		/// <param name="e">Event data that provides an empty dictionary to be populated with
		/// serializable state.</param>
		private void navigationHelper_SaveState( object sender, SaveStateEventArgs e )
		{
			if ( this.foldersViewSource.View != null )
			{
				var selectedItem = ( eLukFolder ) this.foldersViewSource.View.CurrentItem;
				if ( selectedItem != null )
					e.PageState[ "SelectedItem" ] = selectedItem.Name;
			}
		}

		#region Logical page navigation

		// The split page isdesigned so that when the Window does have enough space to show
		// both the list and the dteails, only one pane will be shown at at time.
		//
		// This is all implemented with a single physical page that can represent two logical
		// pages.  The code below achieves this goal without making the user aware of the
		// distinction.

		private const int MinimumWidthForSupportingTwoPanes = 768;

		/// <summary>
		/// Invoked to determine whether the page should act as one logical page or two.
		/// </summary>
		/// <returns>True if the window should show act as one logical page, false
		/// otherwise.</returns>
		private bool UsingLogicalPageNavigation()
		{
			return Window.Current.Bounds.Width < MinimumWidthForSupportingTwoPanes;
		}

		/// <summary>
		/// Invoked with the Window changes size
		/// </summary>
		/// <param name="sender">The current Window</param>
		/// <param name="e">Event data that describes the new size of the Window</param>
		private void Window_SizeChanged( object sender, Windows.UI.Core.WindowSizeChangedEventArgs e )
		{
			this.InvalidateVisualState();
		}

		/// <summary>
		/// Invoked when an item within the list is selected.
		/// </summary>
		/// <param name="sender">The GridView displaying the selected item.</param>
		/// <param name="e">Event data that describes how the selection was changed.</param>
		private void ItemListView_SelectionChanged( object sender, SelectionChangedEventArgs e )
		{
			// Invalidate the view state when logical page navigation is in effect, as a change
			// in selection may cause a corresponding change in the current logical page.  When
			// an item is selected this has the effect of changing from displaying the item list
			// to showing the selected item's details.  When the selection is cleared this has the
			// opposite effect.

			if ( this.UsingLogicalPageNavigation() )
				this.InvalidateVisualState();
		}

		private bool CanGoBack()
		{
			return false;
			//if ( this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null )
			//{
			//	return true;
			//}
			//else
			//{
			//	return this.navigationHelper.CanGoBack();
			//}
		}
		private void GoBack()
		{
			//if ( this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null )
			//{
			//	// When logical page navigation is in effect and there's a selected item that
			//	// item's details are currently displayed.  Clearing the selection will return to
			//	// the item list.  From the user's point of view this is a logical backward
			//	// navigation.
			//	this.itemListView.SelectedItem = null;
			//}
			//else
			//{
			//	this.navigationHelper.GoBack();
			//}
		}

		private void InvalidateVisualState()
		{
			var visualState = DetermineVisualState();
			VisualStateManager.GoToState( this, visualState, false );
			this.navigationHelper.GoBackCommand.RaiseCanExecuteChanged();
		}

		/// <summary>
		/// Invoked to determine the name of the visual state that corresponds to an application
		/// view state.
		/// </summary>
		/// <returns>The name of the desired visual state.  This is the same as the name of the
		/// view state except when there is a selected item in portrait and snapped views where
		/// this additional logical page is represented by adding a suffix of _Detail.</returns>
		private string DetermineVisualState()
		{
			if ( !UsingLogicalPageNavigation() )
				return "PrimaryView";

			// Update the back button's enabled state when the view state changes
			var logicalPageBack = this.UsingLogicalPageNavigation();
			//var logicalPageBack = this.UsingLogicalPageNavigation() && this.itemListView.SelectedItem != null;

			return logicalPageBack ? "SinglePane_Detail" : "SinglePane";
		}

		#endregion

		#region NavigationHelper registration

		/// The methods provided in this section are simply used to allow
		/// NavigationHelper to respond to the page's navigation methods.
		/// 
		/// Page specific logic should be placed in event handlers for the  
		/// <see cref="GridCS.Common.NavigationHelper.LoadState"/>
		/// and <see cref="GridCS.Common.NavigationHelper.SaveState"/>.
		/// The navigation parameter is available in the LoadState method 
		/// in addition to page state preserved during an earlier session.

		protected override void OnNavigatedTo( NavigationEventArgs e )
		{
			navigationHelper.OnNavigatedTo( e );
		}

		protected override void OnNavigatedFrom( NavigationEventArgs e )
		{
			navigationHelper.OnNavigatedFrom( e );
		}

		#endregion

		private void messageListView_SelectionChanged( object sender, SelectionChangedEventArgs e )
		{

		}

		private void messageListView_ItemClick( object sender, ItemClickEventArgs e )
		{
			MailMessage message = e.ClickedItem as MailMessage;
			if ( message != null )
			{
				this.ShowMessage( message );
			}
		}

		private void ShowMessage( MailMessage message )
		{
			if ( message.To.Count <= 0 )
				return;
			txtFrom.Text = message.From.DisplayName;
			txtTo.Text = message.To.Count > 0 ? message.To[ 0 ].DisplayName : "Unknown Account";
			txtSubject.Text = message.Subject;
			imgAccountProfile.Source = Misc.GetDefaultProfilePicture();
			//imgAccountProfile.Source = eLuk.CommandEngine.Misc.GetBitmap( message.From.ProfilePictureRaw, ( int ) imgAccountProfile.Width, ( int ) imgAccountProfile.Height );
			wvMessageBody.NavigateToString( "" );

			if ( message.MessageContents.Count > 0 )
			{
				message.HtmlBody = message.MessageContents.FirstOrDefault( f => f.ContentType.Type == "text/html" ).Content;
				if ( message.HtmlBody != null && message.HtmlBody.Trim() != "" )
				{
					wvMessageBody.NavigateToString( message.HtmlBody );
				}
				else
				{
					message.TextBody = message.MessageContents.FirstOrDefault( f => f.ContentType.Type == "text/plain" ).Content;
					if ( message.TextBody != null && message.TextBody.Trim() != "" )
					{
						wvMessageBody.NavigateToString( message.TextBody );
					}
				}
			}
		}

		private void SetProfileImage( byte[] bytes, Image image )
		{
			using ( InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream() )
			{
				using ( DataWriter writer = new DataWriter( stream.GetOutputStreamAt( 0 ) ) )
				{
					writer.WriteBytes( bytes );
					writer.StoreAsync().GetResults();
				}

				BitmapImage bimage = new BitmapImage();
				bimage.SetSource( stream );
				image.Source = bimage;
			}
		}

		private void SelectFolder( eLukFolder folder )
		{
			if ( folder != null && folder.MailMessages != null )
			{
				this.DefaultViewModel[ "eLukMessages" ] = folder.MailMessages;
				//this.DefaultViewModel[ "eLukMessages" ] = folder.MailMessages.OrderByDescending(m=>m.;
				int total = folder.MailMessages.Count();
				int seen = folder.MailMessages.Count( f => f.Seen == true );
				pageTitle.Text = folder.Name + " ( Having " + total.ToString() + " messages and " + seen.ToString() + " seen) ";
				MailMessage message = folder.MailMessages.FirstOrDefault();
				this.ShowMessage( message );
			}
		}

		private void btnFolder_Click( object sender, RoutedEventArgs e )
		{
			//var flyout = new eLukFolderView();
			folderViewFlyout.ShowIndependent();
		}

		private void btnDelete_Click( object sender, RoutedEventArgs e )
		{

		}

		private async void btnLogin_Click( object sender, RoutedEventArgs e )
		{
			if ( txtLoginEmailID.Text.Trim() == "" || txtLoginPassword.Password.Trim() == "" )
			{
				return;
			}

			await App.IniteLuk( "", "", txtLoginEmailID.Text, txtLoginPassword.Password );

			EmailAccount emailAccount = null;
			eLukFolder root = null;
			await Task.Run( () =>
			{
				emailAccount = App.eLukComponent.SubComponents.Find( g => g.UniqueId == "email" ).eLukObject as EmailAccount;
				root = emailAccount.IMAPFolder;
			} );

			if ( root != null )
			{
				if ( loginPopup.IsOpen )
				{
					loginPopup.IsOpen = false;
				}

				if ( App.eLukLocalLoginStatus || ( emailAccount.UserName == txtLoginEmailID.Text && emailAccount.Password == txtLoginPassword.Password ) )
				{
					if ( !this.UsingLogicalPageNavigation() && this.foldersViewSource.View != null )
					{
						this.foldersViewSource.View.MoveCurrentToFirst();
					}

					this.DefaultViewModel[ "eLukFolders" ] = root.SubFolders;
					this.folderViewFlyout = new eLukFolderView( root.SubFolders );
					this.folderViewFlyout.FolderSelectionChanged += folderViewFlyout_FolderSelectionChanged;
					this.SelectFolder( root.SubFolders.FirstOrDefault() );
				}
				else
				{
					root = null;
					emailAccount.IMAPFolder = null;
				}
			}

			if ( root == null )
			{
				if ( !progressPopup.IsOpen )
				{
					loginPopup.IsOpen = false;
					progressPopupContent.Width = Window.Current.Bounds.Width;
					progressPopup.IsOpen = true;
					progressRing.FlowDirection = Windows.UI.Xaml.FlowDirection.LeftToRight;
					progressRing.IsActive = true;

					await App.InitSession( "", "", txtLoginEmailID.Text, txtLoginPassword.Password );

					await App.IMAPSession.SyncMailClient();

					//////if ( progressPopup.IsOpen == true )
					//////	progressPopup.IsOpen = false;

					//////if ( !this.UsingLogicalPageNavigation() && this.foldersViewSource.View != null )
					//////{
					//////	this.foldersViewSource.View.MoveCurrentToFirst();
					//////}

					//////if ( root != null )
					//////{
					//////	this.DefaultViewModel[ "eLukFolders" ] = root.SubFolders;
					//////	this.folderViewFlyout = new eLukFolderView( root.SubFolders );
					//////	this.folderViewFlyout.FolderSelectionChanged += folderViewFlyout_FolderSelectionChanged;
					//////	this.SelectFolder( root.SubFolders.FirstOrDefault() );
					//////}
				}

				return;
			}

		}

		private void btnCancelLogin_Click( object sender, RoutedEventArgs e )
		{
			App.Current.Exit();
		}

		private async void Sync_Clicked( object sender, RoutedEventArgs e )
		{
			syncProgressBar.IsActive = true;
			syncProgressBar.Visibility = Windows.UI.Xaml.Visibility.Visible;
			abbSync.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
			await App.IMAPSession.SyncMailClient();
			syncProgressBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
			abbSync.Visibility = Windows.UI.Xaml.Visibility.Visible;
			syncProgressBar.IsActive = false;
		}

		private void Setting_Clicked( object sender, RoutedEventArgs e )
		{
			var flyout = new eLukSettings();
			flyout.ShowIndependent();
		}

		private async void App_eLukComponentUpdated( object sender, eLukComponentUpdatedEventArgs e )
		{
			if ( e.Option == Runtime.OperationOption.AuthenticationFailed )
			{
				if ( e.Message != null && e.Message.Trim() != "" )
					txtProgressMessage.Text = e.Message;

				await Task.Delay( 2000 );

				if ( progressPopup.IsOpen == true )
					progressPopup.IsOpen = false;
				
				if ( loginPopup.IsOpen == false )
					loginPopup.IsOpen = true;


				return;
			}
			else if ( e.Option == Runtime.OperationOption.Ready )
			{

				if ( progressPopup.IsOpen == true )
					progressPopup.IsOpen = false;

				if ( !this.UsingLogicalPageNavigation() && this.foldersViewSource.View != null )
				{
					this.foldersViewSource.View.MoveCurrentToFirst();
				}

				EmailAccount emailAccount = null;
				eLukFolder root = null;
				await Task.Run( () =>
				{
					emailAccount = App.eLukComponent.SubComponents.Find( g => g.UniqueId == "email" ).eLukObject as EmailAccount;
					root = emailAccount.IMAPFolder;
				} );

				if ( root != null )
				{
					this.DefaultViewModel[ "eLukFolders" ] = root.SubFolders;
					this.folderViewFlyout = new eLukFolderView( root.SubFolders );
					this.folderViewFlyout.FolderSelectionChanged += folderViewFlyout_FolderSelectionChanged;
					this.SelectFolder( root.SubFolders.FirstOrDefault() );
				}
				return;
			}
			else if ( e.Option == Runtime.OperationOption.StatusUpdate )
			{
				if ( e.Message != null && e.Message.Trim() != "" )
					txtProgressMessage.Text = e.Message;
			}

		}

		private void txtLoginEmailID_GotFocus( object sender, RoutedEventArgs e )
		{
			if ( txtLoginEmailID.Text == "Your email id" )
			{
				txtLoginEmailID.Text = "";
				txtLoginEmailID.Foreground = new SolidColorBrush( Windows.UI.Colors.Black );
			}
		}

		private void txtLoginEmailID_LostFocus( object sender, RoutedEventArgs e )
		{
			if ( txtLoginEmailID.Text == "" )
			{
				txtLoginEmailID.Text = "Your email id";
				txtLoginEmailID.Foreground = new SolidColorBrush( Windows.UI.Colors.LightGray );
			}
		}
	}
}